package com.car.service.websocket;

import com.car.service.dto.MessageDTO;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * WebSocket服务端点
 */
@Slf4j
@Component
@ServerEndpoint("/ws/chat/{userId}/{userType}")
public class ChatWebSocketServer {
    
    /**
     * 当前在线连接数
     */
    private static AtomicInteger onlineCount = new AtomicInteger(0);
    
    /**
     * 用户ID -> WebSocket Session
     */
    private static Map<String, Session> sessionMap = new ConcurrentHashMap<>();
    
    /**
     * JSON转换器
     */
    private static ObjectMapper objectMapper = new ObjectMapper();
    
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId, @PathParam("userType") String userType) {
        // 将当前用户添加到sessionMap
        String key = generateKey(userId, userType);
        sessionMap.put(key, session);
        
        // 在线数加1
        int count = onlineCount.incrementAndGet();
        log.info("有新连接加入，当前在线人数为：{}", count);
        
        // 发送连接成功消息
        try {
            MessageDTO message = MessageDTO.builder()
                    .type("CONNECT")
                    .content("连接成功")
                    .timestamp(System.currentTimeMillis())
                    .build();
            sendMessage(session, message);
        } catch (IOException e) {
            log.error("发送消息失败", e);
        }
    }
    
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("userId") String userId, @PathParam("userType") String userType) {
        // 从sessionMap中删除当前用户
        String key = generateKey(userId, userType);
        sessionMap.remove(key);
        
        // 在线数减1
        int count = onlineCount.decrementAndGet();
        log.info("有一连接关闭，当前在线人数为：{}", count);
    }
    
    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("userId") String userId, @PathParam("userType") String userType) {
        log.info("收到来自用户{}的消息：{}", userId, message);
        
        try {
            // 解析消息
            MessageDTO messageDTO = objectMapper.readValue(message, MessageDTO.class);
            
            // 处理心跳消息
            if ("HEARTBEAT".equals(messageDTO.getType())) {
                MessageDTO heartbeatResponse = MessageDTO.builder()
                        .type("HEARTBEAT")
                        .timestamp(System.currentTimeMillis())
                        .build();
                sendMessage(session, heartbeatResponse);
                return;
            }
            
            // 处理聊天消息
            if ("CHAT".equals(messageDTO.getType())) {
                // 设置发送者信息
                messageDTO.setSenderId(Long.valueOf(userId));
                messageDTO.setSenderType(Integer.valueOf(userType));
                messageDTO.setTimestamp(System.currentTimeMillis());
                
                // 发送给接收者
                String receiverKey = generateKey(messageDTO.getReceiverId().toString(), 
                        messageDTO.getSenderType() == 1 ? "2" : "1");
                Session receiverSession = sessionMap.get(receiverKey);
                
                if (receiverSession != null && receiverSession.isOpen()) {
                    sendMessage(receiverSession, messageDTO);
                } else {
                    // 接收者不在线，存储为离线消息
                    log.info("接收者{}不在线，存储为离线消息", messageDTO.getReceiverId());
                    // TODO: 将消息保存到数据库
                }
                
                // 回复发送成功确认
                MessageDTO confirmMessage = MessageDTO.builder()
                        .type("CONFIRM")
                        .content("消息已发送")
                        .timestamp(System.currentTimeMillis())
                        .build();
                sendMessage(session, confirmMessage);
            }
            
        } catch (Exception e) {
            log.error("处理消息失败", e);
        }
    }
    
    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误", error);
    }
    
    /**
     * 发送消息
     */
    private void sendMessage(Session session, MessageDTO message) throws IOException {
        String messageText = objectMapper.writeValueAsString(message);
        session.getBasicRemote().sendText(messageText);
    }
    
    /**
     * 生成用户key
     */
    private String generateKey(String userId, String userType) {
        return userId + "_" + userType;
    }
    
    /**
     * 获取在线人数
     */
    public static int getOnlineCount() {
        return onlineCount.get();
    }
} 